static int setup_guestos(
int dom, int kernel_fd, int initrd_fd, unsigned long tot_pages,
- unsigned long virt_load_addr, size_t ksize, dom_meminfo_t *meminfo)
+ unsigned long virt_load_addr, size_t ksize,
+ dom0_builddomain_t *builddomain)
{
l1_pgentry_t *vl1tab = NULL, *vl1e = NULL;
l2_pgentry_t *vl2tab = NULL, *vl2e = NULL;
unsigned long num_pgt_updates = 0;
unsigned long count, pt_start, i, j;
- memset(meminfo, 0, sizeof(*meminfo));
+ memset(builddomain, 0, sizeof(*builddomain));
if ( init_pfn_mapper() < 0 )
goto error_out;
}
/* 'i' is 'ksize' rounded up to a page boundary. */
- meminfo->virt_mod_addr = virt_load_addr + i;
- meminfo->virt_mod_len = isize;
+ builddomain->virt_mod_addr = virt_load_addr + i;
+ builddomain->virt_mod_len = isize;
for ( j = 0; j < isize; j += PAGE_SIZE, i += PAGE_SIZE )
{
*/
l2tab = page_array[alloc_index] << PAGE_SHIFT;
alloc_index--;
- meminfo->l2_pgt_addr = l2tab;
+ builddomain->l2_pgt_addr = l2tab;
/*
* Pin down l2tab addr as page dir page - causes hypervisor to provide
num_pgt_updates++;
}
- meminfo->virt_startinfo_addr =
+ builddomain->virt_startinfo_addr =
virt_load_addr + ((alloc_index-1)<<PAGE_SHIFT);
/* Send the page update requests down to the hypervisor. */
}
if ( setup_guestos(domain_id, kernel_fd, initrd_fd, tot_pages,
- load_addr, ksize, &launch_op.u.meminfo) < 0 )
+ load_addr, ksize, &launch_op.u.builddomain) < 0 )
return 1;
if ( initrd_fd >= 0 )
close(initrd_fd);
close(kernel_fd);
- launch_op.u.meminfo.domain = domain_id;
- launch_op.u.meminfo.virt_load_addr = load_addr;
- launch_op.u.meminfo.num_vifs = atoi(argv[3]);
- launch_op.u.meminfo.cmd_line[0] = '\0';
+ launch_op.u.builddomain.domain = domain_id;
+ launch_op.u.builddomain.virt_load_addr = load_addr;
+ launch_op.u.builddomain.num_vifs = atoi(argv[3]);
+ launch_op.u.builddomain.cmd_line[0] = '\0';
cmd_len = 0;
for ( count = args_start; count < argc; count++ )
{
ERROR("Size of image boot params too big!\n");
break;
}
- strcat(launch_op.u.meminfo.cmd_line, argv[count]);
- strcat(launch_op.u.meminfo.cmd_line, " ");
+ strcat(launch_op.u.builddomain.cmd_line, argv[count]);
+ strcat(launch_op.u.builddomain.cmd_line, " ");
cmd_len += strlen(argv[count] + 1);
}
dom0_op_t op;
op.cmd = DOM0_STARTDOMAIN;
- op.u.meminfo.domain = id;
+ op.u.startdomain.domain = id;
err = do_dom0_op(&op);
dom0_op_t op;
op.cmd = DOM0_STOPDOMAIN;
- op.u.meminfo.domain = id;
+ op.u.stopdomain.domain = id;
err = do_dom0_op(&op);
MONITOR_BASE := 0xFC500000
# Bootloader should load monitor to this real address
LOAD_BASE := 0x00100000
-CFLAGS := -nostdinc -fno-builtin -O3 -Wall -DMONITOR_BASE=$(MONITOR_BASE)
+#CFLAGS := -nostdinc -fno-builtin -O3 -Wall -DMONITOR_BASE=$(MONITOR_BASE)
CFLAGS += -fomit-frame-pointer -I$(BASEDIR)/include -D__KERNEL__ -DNDEBUG
-#CFLAGS += -fomit-frame-pointer -I$(BASEDIR)/include -D__KERNEL__
+CFLAGS += -fomit-frame-pointer -I$(BASEDIR)/include -D__KERNEL__
LDFLAGS := -T xeno.lds -N
case DOM0_BUILDDOMAIN:
{
- struct task_struct * p = find_domain_by_id(op.u.meminfo.domain);
+ struct task_struct * p = find_domain_by_id(op.u.builddomain.domain);
ret = -EINVAL;
if ( p != NULL )
{
- if ( (ret = final_setup_guestos(p, &op.u.meminfo)) == 0 )
+ if ( (ret = final_setup_guestos(p, &op.u.builddomain)) == 0 )
ret = p->domain;
put_task_struct(p);
}
case DOM0_STARTDOMAIN:
{
- struct task_struct * p = find_domain_by_id(op.u.meminfo.domain);
+ struct task_struct * p = find_domain_by_id(op.u.startdomain.domain);
ret = -EINVAL;
if ( p != NULL )
{
case DOM0_STOPDOMAIN:
{
- ret = stop_other_domain(op.u.meminfo.domain);
+ ret = stop_other_domain(op.u.stopdomain.domain);
}
break;
op.u.getdominfo.mcu_advance = p->mcu_advance;
op.u.getdominfo.tot_pages = p->tot_pages;
op.u.getdominfo.cpu_time = p->cpu_time;
+ memcpy(&op.u.getdominfo.ctxt,
+ &p->shared_info->execution_context,
+ sizeof(execution_context_t));
}
read_unlock_irqrestore(&tasklist_lock, flags);
copy_to_user(u_dom0_op, &op, sizeof(op));
- break;
}
+ break;
+
+ case DOM0_GETPAGEFRAMEINFO:
+ {
+ struct pfn_info *page = frame_table + op.u.getpageframeinfo.pfn;
+
+ op.u.getpageframeinfo.domain = page->flags & PG_domain_mask;
+ op.u.getpageframeinfo.type = NONE;
+ if ( page->type_count & REFCNT_PIN_BIT )
+ {
+ switch ( page->flags & PG_type_mask )
+ {
+ case PGT_l1_page_table:
+ op.u.getpageframeinfo.type = L1TAB;
+ break;
+ case PGT_l2_page_table:
+ op.u.getpageframeinfo.type = L2TAB;
+ break;
+ }
+ }
+
+ copy_to_user(u_dom0_op, &op, sizeof(op));
+ }
+ break;
case DOM0_IOPL:
{
* <one page>
*/
-int final_setup_guestos(struct task_struct * p, dom_meminfo_t * meminfo)
+int final_setup_guestos(struct task_struct *p, dom0_builddomain_t *builddomain)
{
- l2_pgentry_t * l2tab;
start_info_t * virt_startinfo_addr;
unsigned long virt_stack_addr;
unsigned long phys_l2tab;
if ( (p->flags & PF_CONSTRUCTED) )
return -EINVAL;
- /* High entries in page table must contain hypervisor
- * mem mappings - set them up.
- */
- phys_l2tab = meminfo->l2_pgt_addr;
- l2tab = map_domain_mem(phys_l2tab);
- memcpy(&l2tab[DOMAIN_ENTRIES_PER_L2_PAGETABLE],
- &idle_pg_table[DOMAIN_ENTRIES_PER_L2_PAGETABLE],
- (ENTRIES_PER_L2_PAGETABLE - DOMAIN_ENTRIES_PER_L2_PAGETABLE)
- * sizeof(l2_pgentry_t));
- l2tab[PERDOMAIN_VIRT_START >> L2_PAGETABLE_SHIFT] =
- mk_l2_pgentry(__pa(p->mm.perdomain_pt) | __PAGE_HYPERVISOR);
- l2tab[LINEAR_PT_VIRT_START >> L2_PAGETABLE_SHIFT] =
- mk_l2_pgentry(phys_l2tab | __PAGE_HYPERVISOR);
+ /* NB. Page base must already be pinned! */
+ phys_l2tab = builddomain->l2_pgt_addr;
p->mm.pagetable = mk_pagetable(phys_l2tab);
- unmap_domain_mem(l2tab);
+ get_page_type(&frame_table[phys_l2tab>>PAGE_SHIFT]);
+ get_page_tot(&frame_table[phys_l2tab>>PAGE_SHIFT]);
/* set up the shared info structure */
update_dom_time(p->shared_info);
p->shared_info->domain_time = 0;
/* we pass start info struct to guest os as function parameter on stack */
- virt_startinfo_addr = (start_info_t *)meminfo->virt_startinfo_addr;
+ virt_startinfo_addr = (start_info_t *)builddomain->virt_startinfo_addr;
virt_stack_addr = (unsigned long)virt_startinfo_addr;
/* we need to populate start_info struct within the context of the
memset(virt_startinfo_addr, 0, sizeof(*virt_startinfo_addr));
virt_startinfo_addr->nr_pages = p->tot_pages;
virt_startinfo_addr->shared_info = virt_to_phys(p->shared_info);
- virt_startinfo_addr->pt_base = meminfo->virt_load_addr +
+ virt_startinfo_addr->pt_base = builddomain->virt_load_addr +
((p->tot_pages - 1) << PAGE_SHIFT);
/* module size and length */
- virt_startinfo_addr->mod_start = meminfo->virt_mod_addr;
- virt_startinfo_addr->mod_len = meminfo->virt_mod_len;
+ virt_startinfo_addr->mod_start = builddomain->virt_mod_addr;
+ virt_startinfo_addr->mod_len = builddomain->virt_mod_len;
virt_startinfo_addr->dom_id = p->domain;
virt_startinfo_addr->flags = IS_PRIV(p) ? SIF_PRIVILEGED : 0;
/* Add virtual network interfaces and point to them in startinfo. */
- while (meminfo->num_vifs-- > 0) {
+ while (builddomain->num_vifs-- > 0) {
net_vif = create_net_vif(p->domain);
shared_rings = net_vif->shared_rings;
if (!shared_rings) panic("no network ring!\n");
virt_startinfo_addr->blk_ring = virt_to_phys(p->blk_ring_base);
/* Copy the command line */
- strcpy(virt_startinfo_addr->cmd_line, meminfo->cmd_line);
+ strcpy(virt_startinfo_addr->cmd_line, builddomain->cmd_line);
/* Reinstate the caller's page tables. */
__asm__ __volatile__ (
p->flags |= PF_CONSTRUCTED;
new_thread(p,
- (unsigned long)meminfo->virt_load_addr,
+ (unsigned long)builddomain->virt_load_addr,
(unsigned long)virt_stack_addr,
(unsigned long)virt_startinfo_addr);
unmap_domain_mem(l1start);
/* pages that are part of page tables must be read only */
- cur_address = list_entry(p->pg_head.next, struct pfn_info, list) -
- frame_table;
- cur_address <<= PAGE_SHIFT;
- for ( count = 0; count < alloc_index; count++ )
- {
- list_ent = frame_table[cur_address >> PAGE_SHIFT].list.next;
- cur_address = list_entry(list_ent, struct pfn_info, list) -
- frame_table;
- cur_address <<= PAGE_SHIFT;
- }
-
l2tab = l2start + l2_table_offset(virt_load_address +
(alloc_index << PAGE_SHIFT));
l1start = l1tab = map_domain_mem(l2_pgentry_to_phys(*l2tab));
l2tab++;
for ( count = alloc_index; count < p->tot_pages; count++ )
{
- *l1tab++ = mk_l1_pgentry(l1_pgentry_val(*l1tab) & ~_PAGE_RW);
+ *l1tab = mk_l1_pgentry(l1_pgentry_val(*l1tab) & ~_PAGE_RW);
+ page = frame_table + l1_pgentry_to_pagenr(*l1tab);
+ page->flags = dom | PGT_l1_page_table;
+ page->tot_count++;
+ l1tab++;
if( !((unsigned long)l1tab & (PAGE_SIZE - 1)) )
{
unmap_domain_mem(l1start);
l1start = l1tab = map_domain_mem(l2_pgentry_to_phys(*l2tab));
l2tab++;
}
- page = frame_table + (cur_address >> PAGE_SHIFT);
- page->flags = dom | PGT_l1_page_table;
- page->tot_count++;
-
- list_ent = frame_table[cur_address >> PAGE_SHIFT].list.next;
- cur_address = list_entry(list_ent, struct pfn_info, list) -
- frame_table;
- cur_address <<= PAGE_SHIFT;
}
page->type_count |= REFCNT_PIN_BIT;
page->tot_count |= REFCNT_PIN_BIT;
type);
return -1;
}
- ASSERT(page_type_count(page) != 0);
+ ASSERT((page_type_count(page) & ~REFCNT_PIN_BIT) != 0);
put_page_tot(page);
return put_page_type(page);
}
page = frame_table + page_nr;
ASSERT(DOMAIN_OKAY(page->flags));
ASSERT((!writeable) ||
- ((page_type_count(page) != 0) &&
+ (((page_type_count(page) & ~REFCNT_PIN_BIT) != 0) &&
((page->flags & PG_type_mask) == PGT_writeable_page) &&
((page->flags & PG_need_flush) == PG_need_flush)));
if ( writeable )
/* do some accounting */
ranfor = (s32)(now - prev->lastschd);
- ASSERT((ranfor>0));
prev->cpu_time += ranfor;
/* calculate mcu and update avt */
#ifndef __DOM0_OPS_H__
#define __DOM0_OPS_H__
-#define DOM0_GETMEMLIST 2
-#define DOM0_BVTCTL 6
-#define DOM0_ADJUSTDOM 7
-#define DOM0_CREATEDOMAIN 8
-#define DOM0_DESTROYDOMAIN 9
-#define DOM0_STARTDOMAIN 10
-#define DOM0_STOPDOMAIN 11
-#define DOM0_GETDOMAININFO 12
-#define DOM0_BUILDDOMAIN 13
-#define DOM0_IOPL 14
-#define DOM0_MSR 15
-#define DOM0_DEBUG 16
-#define DOM0_SETTIME 17
+#include "hypervisor-if.h"
+
#define MAX_CMD_LEN 256
#define MAX_DOMAIN_NAME 16
+#define DOM0_CREATEDOMAIN 8
typedef struct dom0_newdomain_st
{
/* IN parameters. */
unsigned int domain;
} dom0_newdomain_t;
+#define DOM0_STARTDOMAIN 10
+typedef struct dom0_startdomain_st
+{
+ /* IN parameters. */
+ unsigned int domain;
+} dom0_startdomain_t;
+
+#define DOM0_STOPDOMAIN 11
+typedef struct dom0_stopdomain_st
+{
+ /* IN parameters. */
+ unsigned int domain;
+} dom0_stopdomain_t;
+
+#define DOM0_DESTROYDOMAIN 9
typedef struct dom0_killdomain_st
{
+ /* IN variables. */
unsigned int domain;
int force;
} dom0_killdomain_t;
+#define DOM0_GETMEMLIST 2
typedef struct dom0_getmemlist_st
{
/* IN variables. */
unsigned long num_pfns;
} dom0_getmemlist_t;
-typedef struct domain_launch
+#define DOM0_BUILDDOMAIN 13
+typedef struct dom0_builddomain_st
{
+ /* IN variables. */
unsigned int domain;
unsigned long l2_pgt_addr;
unsigned long virt_load_addr;
char cmd_line[MAX_CMD_LEN];
unsigned long virt_mod_addr;
unsigned long virt_mod_len;
-} dom_meminfo_t;
+ execution_context_t ctxt;
+} dom0_builddomain_t;
+#define DOM0_BVTCTL 6
typedef struct dom0_bvtctl_st
{
- unsigned long ctx_allow; /* context switch allowance */
+ /* IN variables. */
+ unsigned long ctx_allow; /* context switch allowance */
} dom0_bvtctl_t;
+#define DOM0_ADJUSTDOM 7
typedef struct dom0_adjustdom_st
{
- unsigned int domain; /* domain id */
- unsigned long mcu_adv; /* mcu advance: inverse of weight */
- unsigned long warp; /* time warp */
- unsigned long warpl; /* warp limit */
- unsigned long warpu; /* unwarp time requirement */
+ /* IN variables. */
+ unsigned int domain; /* domain id */
+ unsigned long mcu_adv; /* mcu advance: inverse of weight */
+ unsigned long warp; /* time warp */
+ unsigned long warpl; /* warp limit */
+ unsigned long warpu; /* unwarp time requirement */
} dom0_adjustdom_t;
+#define DOM0_GETDOMAININFO 12
typedef struct dom0_getdominfo_st
{
/* IN variables. */
unsigned long mcu_advance;
unsigned int tot_pages;
long long cpu_time;
+ execution_context_t ctxt;
} dom0_getdominfo_t;
+#define DOM0_GETPAGEFRAMEINFO 18
+typedef struct dom0_getpageframeinfo_st
+{
+ /* IN variables. */
+ unsigned long pfn; /* Machine page frame number to query. */
+ /* OUT variables. */
+ unsigned int domain; /* To which domain does the frame belong? */
+ enum { NONE, L1TAB, L2TAB } type; /* Is the page PINNED to a type? */
+} dom0_getpageframeinfo_t;
+
+#define DOM0_IOPL 14
typedef struct dom0_iopl_st
{
unsigned int domain;
unsigned int iopl;
} dom0_iopl_t;
+#define DOM0_MSR 15
typedef struct dom0_msr_st
{
/* IN variables. */
unsigned int out1, out2;
} dom0_msr_t;
+#define DOM0_DEBUG 16
typedef struct dom0_debug_st
{
/* IN variables. */
* Set clock such that it would read <secs,usecs> after 00:00:00 UTC,
* 1 January, 1970 if the current system time was <system_time>.
*/
+#define DOM0_SETTIME 17
typedef struct dom0_settime_st
{
/* IN variables. */
union
{
dom0_newdomain_t newdomain;
+ dom0_startdomain_t startdomain;
+ dom0_stopdomain_t stopdomain;
dom0_killdomain_t killdomain;
dom0_getmemlist_t getmemlist;
dom0_bvtctl_t bvtctl;
dom0_adjustdom_t adjustdom;
- dom_meminfo_t meminfo;
+ dom0_builddomain_t builddomain;
dom0_getdominfo_t getdominfo;
+ dom0_getpageframeinfo_t getpageframeinfo;
dom0_iopl_t iopl;
dom0_msr_t msr;
dom0_debug_t debug;
struct task_struct *p, dom0_newdomain_t *params, unsigned int num_vifs,
char *data_start, unsigned long data_len,
char *cmdline, unsigned long initrd_len);
-extern int final_setup_guestos(struct task_struct *p, dom_meminfo_t *);
+extern int final_setup_guestos(struct task_struct *p, dom0_builddomain_t *);
struct task_struct *find_domain_by_id(unsigned int dom);
extern void release_task(struct task_struct *);